home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Network Supervisor's Toolkit
/
Network Supervisor's Toolkit.iso
/
tools
/
lu62
/
comm
/
fcom.asm
< prev
next >
Wrap
Assembly Source File
|
1996-07-10
|
22KB
|
796 lines
;*******************************************************
;* *
;* Asynchronous communication driver *
;* (for null modem only) *
;* *
;* CopyRight (C) by Nicholas Poljakov. 1995. *
;* *
;*******************************************************
.MODEL SMALL
include i_s.inc
include c:\m61\include\dos.inc
public inbuff, in_cnt, sw_buff, err_cnt, open_type, b_size
public out_buff, out_cnt, out_full, dcl1, dcl2, err1, lock_send, rcv_exit
public rcv_off, rcv_seg, base_addr, port_num, save0b, save0c, tsrsize, my_psp
public blocklt, startblock, ascom, quickexit, nextp, cnt01, fex, cnt00
public ac_open, ac_opn_02, ac_opn_01, ac_opn_1, ac_opn_5, ac_opn_2, ac_opn_3
public ac_opn_4, ac_opn_6, ac_opn_7, setcom1, setcom, ac_opn_retry, ac_opn_8
public ac_opn_9, ac_opn_10, ac_opn_100, ac_opn_101, ac_mdm_act, ac_opn_11
public ac_exit, ac_opn_exit, ac_close, ac_cls_01, ac_cls_02, ac_cls_03
public ac_cls_0, ac_cls_exit, ac_send, sndproc, send_cycl, snd_retry, sndexit
public sendal, send_cycxx, snd_retryx, int6e, int6e_start, popen, int6e_c0
public int6e_c1, int6e_c2, int6e_c3, int6e_c4, ctl_send, when_ready5, int6e_c5
public int6e_exit, io_int, next_int, testnext, receive, z_exit, savelt
public rcvtest0, rcvcycl, rcvtest, callc, io_int_exit, int_exit
.STACK 10h
.DATA
inbuff db 2048 dup (?)
in_cnt dw 0 ;count of received bytes
sw_buff db 0
err_cnt db 0
open_type db 0 ; 50h - open for PORT
b_size db 0 ; size of block for transmition
out_buff dd 0 ; out buffer address
out_cnt dw 0 ; count of bytes that was send
out_full dw 0 ; total of send bytes1
dcl1 db 0ah, 0dh
db 'Async. driver was already installed...$'
dcl2 db 0ah, 0dh
db 'Async. driver is installed.$'
err1 DB 13,10,"Must have DOS 3.0 or higher",13,10,"$"
lock_send db 0
rcv_exit dd 0
org rcv_exit
rcv_off dw ?
rcv_seg dw ?
base_addr dw 0
port_num db 0
save0b db 4 dup (?)
save0c db 4 dup (?)
tsrsize dw 0
my_psp dw 0
BlockLT dw 0
StartBlock db 0
.CODE
;
ascom PROC
;********************************************************
;* *
;* ASync. COMmunication *
;* *
;* Function: Installation of 6E interrupt handler. *
;* The int 6e routine was disigned to support*
;* the COM1 and COM2. *
;* *
;********************************************************
mov ax, _DATA
mov ds, ax
;
; Calculate Tsrsize
;
mov bx, ss
mov ax, es ; PSP address
mov my_psp, ax
sub bx, ax
mov ax, sp
mov cx, 4
shr ax, cl ; convert to paragraphs
add bx, ax
inc bx ; one extra paragraph
mov tsrsize, bx
;
@GetVer ; Get DOS version
cmp al,3 ; Requires DOS 3.0
jge NextP
@ShowStr err1 ; else error and quit
QuickExit:
@Exit
;
NextP:
;*
;* Test if int6e also exist
;*
mov ax,356eh
int 21h
push es
pop ax
cmp ax,0
je cnt00
cnt01:
mov ah,3 ; check function
int 6eh
cmp al,55h ; is the int6e routine active ?
jne cnt00 ; no...
fex:
mov dx, offset dcl1
mov ah, 9
int 21h
jmp QuickExit
cnt00:
push ds
mov ax, _DATA
mov bx, 0ah
mov dx, seg int6e
mov ds, dx
mov word ptr [bx], ax ; save ds for int6e routine
;
mov dx, seg io_int
mov ds, dx
mov bx, 0ah
mov word ptr [bx], ax ; save ds for io_int routine
pop ds
;
push ds ;ß«σαá¡∩Ѽ ds
mov dx,offset int6e ;ds:dx π¬áºδóáεΓ ¡á »α«µÑñπαπ
mov ax,seg int6e ;
mov ds,ax ;
mov al,6eh ;¡«¼Ñα óÑ¬Γ«αá ñ½∩ com1
mov ah,25h ;Σπ¡¬µ¿∩ ¿º¼Ñ¡Ñ¡¿∩ óÑ¬Γ«αá
int 21h ;¼Ñ¡∩Ѽ óÑ¬Γ«α »αÑαδóá¡¿∩
pop ds
;
mov dx, offset dcl2
mov ah, 9
int 21h
;
mov ax, my_psp
mov es, ax
mov ax, word ptr es:[2ch]
mov es, ax
mov ax, 4900h
int 21h ; Free the local environment
mov dx, tsrsize
mov ax,3100h
int 21h
;
ascom ENDP
;*****************************************************
;* *
;* O P E N function *
;* *
;* Input : in AH - function code. *
;* in AL - subfunction code *
;* Output : Return code. ( 0 - OK; -1 - error) *
;*****************************************************
ac_open PROC
;*
;* ES:DX -> init_serial structure
;*
mov bx,dx
;* Save rcv_exit subroutine entry
mov ax, word ptr es:[bx + asc_rcv_exit]
mov rcv_off, ax
mov ax, word ptr es:[bx + asc_rcv_exit + 2]
mov rcv_seg, ax
;
;---»«½πτáѼ íẫóδ⌐ áñαÑß com#
mov al, byte ptr es:[bx + asc_parity]
and al, 0f0h ; clear right bits
mov cl, 4
ror al, cl ; first four bits is com. port number
mov port_num, al ; save com. port number
cmp al, 2 ; high COM number (with int support)
ja ac_opn_02
dec al ; com. num - 1
rol al, 1 ; (com - 1) * 2 - it's displacement in BIOS
mov si, 0
and ax, 00ffh
add si, ax
push es
mov ax,40h ;es π¬áºδóáÑΓ ¡á «í½áßΓ∞ ñá¡¡δσ bios
mov es,ax ;
mov dx,es:[si] ;»«½πτáѼ íẫóδ⌐ áñαÑß com1
pop es
mov base_addr, dx
cmp dx, 0
jne ac_opn_01
ac_opn_02:
mov ax, 0ffffh ; rc = -1 port not present
jmp ac_opn_exit
ac_opn_01:
;---¿¡¿µ¿á½¿º¿απÑ¿ αÑú¿ßΓαδ ñѽ¿Γѽ∩ ߬«α«ßΓ¿ «í¼Ñ¡á
add dx,3 ;π¬áºδóáѼ ¡á αÑú¿ßΓα ¬«¡Γα«½∩ ½¿¡¿¿
in al, dx
jmp short $+2 ; delay for I/O
jmp short $+2 ; delay for I/O
mov al,10000000b ;πßΓá¡áó½¿óáѼ í¿Γ 7
out dx,al ;»«ßδ½áѼ íá⌐Γ
mov ax, word ptr es:[bx + asc_speed]
mov cx, ax
dec dx ;π¬áºδóáѼ ¡á ßΓáαΦ¿⌐ íá⌐Γ ñѽ¿Γѽ∩
dec dx ;߬«α«ßΓ¿ «í¼Ñ¡á
in al, dx
mov ax, cx ; restory ax
jmp short $+2 ; delay for I/O
jmp short $+2 ; delay for I/O
mov al, ah
out dx,al ;»«ßδ½áѼ ßΓáαΦ¿⌐ íá⌐Γ ñѽ¿Γѽ∩
dec dx ;π¬áºδóáѼ ¡á ¼½áñΦ¿⌐ íá⌐Γ ñѽ¿Γѽ∩
in al, dx
jmp short $+2 ; delay for I/O
jmp short $+2 ; delay for I/O
mov ax, cx ; restory ax
out dx,al ;»«ßδ½áѼ ¼½áñΦ¿⌐ íá⌐Γ ñѽ¿Γѽ∩
;
cmp open_type, 50h
je ac_opn_2 ; 8 bits in word
mov al, byte ptr es:[bx + asc_width]
cmp al, 5
jb ac_opn_1
cmp al,8
ja ac_opn_2
jmp ac_opn_3
ac_opn_1:
mov al, 5
jmp ac_opn_3
ac_opn_5:
mov ah, 2
jmp ac_opn_4
ac_opn_2:
mov al, 8
ac_opn_3:
sub al, 5
;---¿¡¿µ¿á½¿º¿απѼ αÑú¿ßΓα ¬«¡Γα«½∩ ½¿¡¿¿
mov ah, byte ptr es:[bx + asc_stops]
cmp ah, 2
ja ac_opn_5
ac_opn_4:
dec ah
mov cl,2
rol ah,cl
or al,ah ; number stop-bits
;
mov ah, byte ptr es:[bx + asc_parity]
and ah, 0fh ; select partity
cmp ah, 1
jne ac_opn_6
or al,00001000b
jmp ac_opn_7
ac_opn_6:
cmp ah,2
jne ac_opn_7
or al,00011000b
ac_opn_7:
add dx,3 ;π¬áºδóáѼ ¡á αÑú¿ßΓα ¬«¡Γα«½∩ ½¿¡¿¿
out dx,al ;»«ßδ½áѼ ¿¡¿µ¿á½¿ºáµ¿«¡¡«Ñ º¡áτÑ¡¿Ñ
;
;---¿¡¿µ¿á½¿º¿απѼ αÑú¿ßΓα αáºαÑΦÑ¡¿∩ »αÑαδóá¡¿∩
;
mov al, byte ptr es:[bx + asc_parity]
and al, 0f0h ; clear right bits
push dx ; save dx
cmp al, 10h ; is it COM1 ?
je SetCom1 ; yes... goto SetCom1
mov bx, 0bh * 4
mov di, offset save0b
jmp SetCom
SetCom1:
mov bx, 0ch * 4
mov di, offset save0c
;
; Set int for COM#
;
SetCom:
mov ax,0
cli
push es
push ds
push ds
pop es
mov ds, ax
mov si, bx
mov cx, 4
rep movsb
pop ds
pop es
;
push es
mov es, ax
mov dx,offset io_int ;ds:dx π¬áºδóáεΓ ¡á »α«µÑñπαπ
mov ax,seg io_int ;int async. processing
mov es:[bx], dx
mov es:[bx + 2], ax
pop es
sti
pop dx
;
ac_opn_retry:
dec dx ;π¬áºδóáѼ ¡á αÑú¿ßΓα αáºαÑΦÑ¡¿∩
dec dx ;»αÑαδóá¡¿∩
in al, dx
jmp short $+2 ; delay for I/O
jmp short $+2 ; delay for I/O
cmp al, 0
je ac_opn_8
inc dx
in al, dx
inc dx
inc dx
inc dx ; line status
in al, dx
inc dx ; modem status
in al, dx
mov dx, base_addr
in al, dx
inc dx
mov al, 0
out dx, al
inc dx
inc dx
jmp ac_opn_retry
ac_opn_8:
mov err_cnt, 0
cli ; Disable interrupts
in al,21h ; port 21h, 8259-1 int IMR
and al,0E7h
cmp port_num, 1 ; COM1 ?
jne ac_opn_9 ; no it's COM2
or al, 00001000b
jmp short ac_opn_10
ac_opn_9:
or al, 00010000b
ac_opn_10:
out 21h,al ; port 21h, 8259-1 int comands
jmp short $+2 ; delay for I/O
jmp short $+2 ; delay for I/O
in al, 21h
cmp port_num, 1 ; is't COM1 ?
jne ac_opn_100 ; no it's COM2...
test al, 00010000b ; it's COM1
jz ac_opn_101
and al, 11101111b
out 21h, al
jmp ac_opn_101
ac_opn_100:
test al, 00001000b
jz ac_opn_101
and al, 11110111b
out 21h, al
ac_opn_101:
mov al,1 ;páºpÑΦáѼ »αÑαδóá¡¿∩
out dx,al ;»«ßδ½áѼ íá⌐Γ
inc dx
inc dx
inc dx
ac_mdm_act:
mov al, 0bh ; activate modem
out dx, al
inc dx
inc dx
jmp short $+2 ; delay for I/O
jmp short $+2 ; delay for I/O
in al, dx
dec dx
jmp short $+2 ; delay for I/O
jmp short $+2 ; delay for I/O
in al, dx
test al, 0eh
jz ac_exit
test al, 00000001b
jz ac_opn_11
mov dx, base_addr
in al, dx
jmp short $+2 ; delay for I/O
jmp short $+2 ; delay for I/O
inc dx
in al, dx
jmp short $+2 ; delay for I/O
jmp short $+2 ; delay for I/O
mov al, 0
out dx, al
jmp short $+2 ; delay for I/O
jmp short $+2 ; delay for I/O
mov al, 1
out dx, al
add dx, 3
jmp ac_mdm_act
ac_opn_11:
dec dx
inc err_cnt
cmp err_cnt, 10
ja ac_exit
jmp ac_mdm_act
ac_exit:
sti ; Enable interrupts
mov err_cnt, 0
;
mov ax, 0 ; ret. code
ac_opn_exit:
ret
ac_open ENDP
;
;*****************************************************
;* *
;* C L O S E function *
;* *
;* Input : in AH - function code. *
;* Output : Return code. ( 0 - OK; -1 - error) *
;*****************************************************
ac_close PROC
;*
;* Close subroutine
;*
;* In al port number (1 or 2)
;*
cmp al, port_num
je ac_cls_01
jmp ac_cls_exit
ac_cls_01:
cmp al, 1
jne ac_cls_02
mov di, 0bh * 4
mov si, offset save0b
jmp short ac_cls_03
ac_cls_02:
mov di, 0ch * 4
mov si, offset save0c
ac_cls_03:
mov ax, 0
push es
mov es, ax
mov cx, 4
cli
rep movsb
pop es
;---»«½πτáѼ íẫóδ⌐ áñαÑß
mov dx,base_addr ;»«½πτáѼ íẫóδ⌐ áñαÑß
cmp dx,0
jne ac_cls_0
jmp ac_cls_exit
;
ac_cls_0:
inc dx
mov al,0 ;ºá»pÑΘáѼ »αÑαδóá¡¿∩
out dx,al ;»«ßδ½áѼ íá⌐Γ
ac_cls_exit:
sti
ret
ac_close ENDP
;
;*****************************************************
;* *
;* S E N D function *
;* *
;* Input : in AH - function code. *
;* in es:dx pointer to block; *
;* in cx - length of block *
;* *
;* Output : Return code. ( 0 - OK; -1 - error) *
;*****************************************************
ac_send PROC
and cx, cx ; is length valid ?
jnz SndProc
cmp cx, 2048
jbe SndProc
jmp SndExit
SndProc:
mov lock_send, 0 ; send no locking
mov bx, offset out_buff
mov word ptr [bx], dx ; save offset and
mov word ptr [bx + 2], es ; segment of out buffer
mov out_full, cx ; save out counter
mov out_cnt, 0 ; initial value
mov si, dx
sti ; enable int.'s
mov al, 65h ; send StartBlock indicator
call SendAL
jmp short $+2 ; delay for I/O
jmp short $+2 ; delay for I/O
jmp short $+2 ; delay for I/O
jmp short $+2 ; delay for I/O
jmp short $+2 ; delay for I/O
jmp short $+2 ; delay for I/O
mov al, cl ; send low byte of length
call SendAl
mov al, ch ; send high byte of length
call SendAl
jmp short $+2 ; delay for I/O
jmp short $+2 ; delay for I/O
jmp short $+2 ; delay for I/O
jmp short $+2 ; delay for I/O
jmp short $+2 ; delay for I/O
jmp short $+2 ; delay for I/O
send_cycl:
cmp lock_send, 0 ; enable send ?
jne send_cycl ; that must be replaced !!!
mov ah, byte ptr es:[si]
add dx, 5
snd_retry:
in al,dx
test al,00100000b ; ready to send ?
jz snd_retry
sub dx, 5
mov al, ah
out dx, al
dec out_full
inc out_cnt
inc si ; next byte
;
loop send_cycl
;
SndExit:
ret
ac_send ENDP
;***************************************************
;* Send Byte from AL *
;* *
;* Function : Send on async. port one byte. *
;* Input : In AL byte for send. *
;* *
;***************************************************
SendAL PROC
push ax
mov dx, base_addr
send_cycXX:
cmp lock_send, 0 ; enable send ?
jne send_cycXX ; that must be replaced !!!
add dx, 5
snd_retryX:
in al,dx
test al,00100000b ; ready to send ?
jz snd_retryX
sub dx, 5
pop ax
out dx, al
ret
SendAL ENDP
;*****************************************************
;* *
;* Int 6E handler *
;* *
;* Input : in AH - function code. *
;* (and for send function ) *
;* in ds:dx pointer to block; *
;* in cx - length of block *
;* *
;* Output : Return code. ( 0 - OK; -1 - error) *
;*****************************************************
int6e PROC far
push bx
push cx
push dx
push si
push di
push ds
push es
push bp
mov bp, sp
;
jmp int6e_start
dw 0
int6e_start:
push ds
pop es ; change ds and es
push ax
mov bx, 0ah
mov ax, word ptr cs:[bx]
mov ds, ax ; restory ds
pop ax
cmp ah,0 ; "open" function ?
jne int6e_c0
mov open_type, al ; Open for "PORT"
cmp al, 50h ; open for PORT ?
je Popen
mov ax, 0ffffh ; bad return code;
jmp int6e_exit
Popen:
call ac_open
jmp int6e_exit
int6e_c0:
cmp ah,1 ; "close" function ?
jne int6e_c1
call ac_close
jmp int6e_exit
int6e_c1:
cmp ah,2 ; "send" function ?
jne int6e_c2
call ac_send
jmp int6e_exit
int6e_c2:
cmp ah,3 ; "test" function ?
jne int6e_c3
mov al,55h
int6e_c3:
cmp ah,4 ; "Get stat" function ?
jne int6e_c5
cmp al, 0 ; Send status ?
jne int6e_c4
mov ax, out_full ; Rest bytes for send
jmp int6e_exit
int6e_c4:
cmp al, 2 ; Send xoff ?
jne int6e_exit
mov out_full, 0
mov al, 19h
ctl_send:
mov dx, base_addr
add dx, 5 ; line status
when_ready5:
in al, dx
test al, 00100000b ; ready to send ?
jz when_ready5 ; retry
sub dx, 5
out dx, al
jmp int6e_exit
int6e_c5:
cmp al, 3 ; Send xon ?
jne int6e_exit
mov out_full, 0
mov al, 17h ; xon
jmp ctl_send
;
int6e_exit:
pop bp
pop es
pop ds
pop di
pop si
pop dx
pop cx
pop bx
iret
int6e ENDP
;*****************************************************
;* *
;* Handler for I/O interrupt *
;* *
;*****************************************************
io_int PROC far
push ax
push bx
push cx
push dx
push si
push di
push ds
push es
;
jmp short $ + 4
dw 0
mov bx, 0ah
mov ax, word ptr cs:[bx]
mov ds, ax ; restory DS
;
Next_int:
mov dx, base_addr ;íẫóδ⌐ áñαÑß
add dx, 2 ; int. identification
in al, dx
add dx, 3 ; line status
in al, dx
test al, 00001110b ; errors ?
jz TestNext
jmp io_int_exit
TestNext:
test al, 00000001b ; was byte received ?
jnz receive
jmp io_int_exit
;
;
; Receive subroutine
;
;
receive:
mov si, offset inbuff
xor bx, bx
sub dx, 4
xor ax, ax
out dx, al ; disable Com# interrupt
dec dx
in al, dx
cmp StartBlock, 65h
je SaveLt
mov StartBlock, al
Z_exit:
inc dx
mov al, 1 ; enable RECEIVE interrupt
out dx, al
jmp io_int_exit
SaveLt:
mov byte ptr BlockLT, al ; save low byte of length
add dx,5 ;π¬áºδóáѼ ¡á αÑú¿ßΓα ßΓáΓπßá ½¿¡¿¿
RcvTest0:
in al,dx ;»«½πτáѼ íá⌐Γ ßΓáΓπßá
test al,00000001b ;»α«óÑα∩Ѽ »«½πτÑ¡δ ½¿ ñá¡¡δÑ
jz RcvTest0
sub dx, 5
in al,dx ;τ¿ΓáѼ »«½πτÑ¡¡δ⌐ ß¿¼ó«½
mov byte ptr BlockLT + 1, al ; save high byte of length
mov cx, BlockLT
and cx, cx
jnz RcvCycl
mov StartBlock, 0
jmp Z_exit
RcvCycl:
add dx,5 ;π¬áºδóáѼ ¡á αÑú¿ßΓα ßΓáΓπßá ½¿¡¿¿
RcvTest:
in al,dx ;»«½πτáѼ íá⌐Γ ßΓáΓπßá
; test al,00011110b ;»α«óÑα∩Ѽ ¡á «Φ¿í¬π
; jnz error_routine ;Ñß½¿ ñá, Γ« ¡á «íαáí«Γ¬π «Φ¿í¬¿
test al,00000001b ;»α«óÑα∩Ѽ »«½πτÑ¡δ ½¿ ñá¡¡δÑ
jz RcvTest
sub dx, 5
in al,dx ;τ¿ΓáѼ »«½πτÑ¡¡δ⌐ ß¿¼ó«½
mov byte ptr [si + bx], al
inc bx
loop RcvCycl
mov StartBlock, 0
;*
;* Block ready. Call EXIT routine
;*
mov cx, bx
mov dx, si
CallC:
;
push dx ; call
push ds ; with "C"
push cx ; convensions
mov ax, 2
pushf ; Call "_interrupt" function
call rcv_exit
add sp, 6
;
mov b_size, 0 ; reset size of buffer
mov dx, base_addr
inc dx
mov al, 1
out dx, al ; enable RECEIVE interrupt
io_int_exit:
mov dx,base_addr ;íẫóδ⌐ áñαÑß
inc dx ;π¬áºδóáѼ ¡á αÑú¿ßΓα ¿ñÑ¡Γ¿Σ¿¬áµ¿¿
inc dx ;»αÑαδóá¡¿∩
in al,dx ;τ¿ΓáѼ Ñú« º¡áτÑ¡¿Ñ
test al,1 ;»α«óÑα∩Ѽ í¿Γ 1 (interrupt pending)
jnz Int_exit
jmp Next_int ;Ñß½¿ «¡ πßΓá¡«ó½Ñ¡, Γ« ¡á ¡áτὫ
Int_exit:
mov al, 20h
out 20h, al
;
pop es
pop ds
pop di
pop si
pop dx
pop cx
pop bx
pop ax
iret
io_int ENDP
;
END ascom